子查询
1. 什么是子查询?
子查询(Subquery)是嵌套在另一个查询中的查询。它可以出现在 SELECT、FROM、WHERE 等子句中,用于从数据库中获取数据或进行复杂的条件过滤。子查询可以返回单个值、一列值或一个表。
1.1 子查询的类型
子查询主要分为以下几种类型:
- 标量子查询(Scalar Subquery):返回单个值的子查询。
- 列子查询(Column Subquery):返回一列值的子查询。
- 行子查询(Row Subquery):返回一行值的子查询。
- 表子查询(Table Subquery):返回一个表的子查询。
2. 子查询的基本语法
子查询的基本语法如下:
SELECT column_name
FROM table_name
WHERE column_name operator (SELECT column_name FROM table_name WHERE condition);
其中:
operator可以是=,>,<,>=,<=,<>,IN,NOT IN,ANY,ALL等。- 子查询必须用括号
()括起来。
3. 子查询的示例
3.1 标量子查询
标量子查询返回单个值,通常用于 WHERE 子句中。
示例: 查找工资高于平均工资的员工。
SELECT employee_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
3.2 列子查询
列子查询返回一列值,通常用于 IN 或 NOT IN 子句中。
示例: 查找在特定部门工作的员工。
SELECT employee_name
FROM employees
WHERE department_id IN (SELECT department_id FROM departments WHERE department_name = 'Sales');
3.3 行子查询
行子查询返回一行值,通常用于 IN 或 NOT IN 子句中。
示例: 查找工资最高的员工。
SELECT employee_name, salary
FROM employees
WHERE (salary, department_id) = (SELECT MAX(salary), department_id FROM employees GROUP BY department_id);
3.4 表子查询
表子查询返回一个表,通常用于 FROM 子句中。
示例: 查找每个部门的平均工资。
SELECT department_name, avg_salary
FROM (SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id) AS dept_avg
JOIN departments ON dept_avg.department_id = departments.department_id;
4. 子查询的注意事项
- 性能问题:子查询可能会影响查询性能,尤其是在嵌套多层子查询时。应尽量简化子查询或使用连接(JOIN)来替代。
- 相关子查询:相关子查询(Correlated Subquery)是指子查询依赖于外部查询的某个值。相关子查询的执行效率通常较低,应谨慎使用。
5. 实践练习
练习 1:标量子查询
任务:查找工资高于公司平均工资的员工。
提示:使用标量子查询计算公司平均工资。
SELECT employee_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
练习 2:列子查询
任务:查找在销售部门工作的员工。
提示:使用列子查询获取销售部门的 department_id。
SELECT employee_name
FROM employees
WHERE department_id IN (SELECT department_id FROM departments WHERE department_name = 'Sales');
练习 3:行子查询
任务:查找每个部门的最高工资员工。
提示:使用行子查询获取每个部门的最高工资。
SELECT employee_name, salary
FROM employees
WHERE (salary, department_id) = (SELECT MAX(salary), department_id FROM employees GROUP BY department_id);
练习 4:表子查询
任务:查找每个部门的平均工资。
提示:使用表子查询计算每个部门的平均工资。
SELECT department_name, avg_salary
FROM (SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id) AS dept_avg
JOIN departments ON dept_avg.department_id = departments.department_id;
6. 总结
子查询是 SQL 中强大的工具,能够帮助我们处理复杂的查询需求。通过本教程,你应该已经掌握了子查询的基本概念、类型、语法和使用场景。在实际应用中,合理使用子查询可以大大提高查询的灵活性和效率。
继续练习和探索,你将能够更加熟练地运用子查询来解决各种数据库查询问题。